<?php
class WechatController extends BaseController
{
    protected $webConfig;
    public $order;
    public $data;
    public function RefundAction()
    {
        $db        = $this->mysql();
        $config    = $db->select('config', '*');
        $webConfig = [];
        foreach ($config as $key => $value) {
            $webConfig[$value['name']] = $value['value'];
        }
        file_put_contents('apiclient_key.pem', $webConfig['wechat_key']);
        file_put_contents('apiclient_cert.pem', $webConfig['wechat_cert']);

        $order = $db->select('cecharge_order', '*', [
            'deletetime' => null,
            'pay_list'   => '已支付',
            'status'     => 'error',
            'refund'     => null,
        ]);
        
        if (!empty($order)) {
            foreach ($order as $key => $value) {

                $pay_info = json_decode($value['pay_info'], true);

                $out_refund_no = 'R' . time() . mt_rand(1, 100);
                $param         = [
                    'appid'         => $pay_info['appid'],
                    'mch_id'        => $pay_info['mch_id'],
                    'nonce_str'     => $this->createNoncestr(32), //这个是随机数 自己封装去吧。。。
                    'out_refund_no' => $out_refund_no,
                    'out_trade_no'  => $pay_info['out_trade_no'],
                    'total_fee'     => intval($pay_info['total_fee'] * 100),
                    'refund_fee'    => intval($pay_info['total_fee'] * 100),
                    'notify_url'    => $webConfig['refund_notify_url'],
                ];
                $param['sign'] = $this->getSign($param, $webConfig['pay_key']);
                $xmldata       = $this->arrayToXml($param);
                $xmlresult     = $this->postXmlSSLCurl($xmldata, 'https://api.mch.weixin.qq.com/secapi/pay/refund');
                $result        = $this->xmlToArray($xmlresult);
                $this->order   = $value;
                if ($result['return_code'] == 'SUCCESS') {
                    if ($this->order['balance'] > 0) {
                        $result = $db->action(function ($database) {

                            // 获取上一级用户信息
                            $account_balance = $database->get('user', 'account_balance', [
                                'user_number' => $this->order['user_number'],
                            ]);
                            // 加入资金变动明细
                            $database->insert('user_money_log', [
                                'order_number' => $this->order['order_number'],
                                'user_number'  => $this->order['user_number'],
                                'before'       => $account_balance,
                                'money'        => $this->order['balance'],
                                'after'        => $account_balance + $this->order['balance'],
                                'state'        => '订单超时退款',
                                'type'         => '退款',
                                'other'        => $this->order['user_number'],
                                'createtime'   => time(),
                            ]);
                            if ($database->id() < 1) {
                                dump_log('退款： ' . $this->order['order_number'] . ' 状态： 退款失败', 'cash_bonus_error.txt');
                                return false;
                            }

                            // 更新钱包数据
                            $res = $database->update('user', [
                                'account_balance[+]' => $this->order['balance'],
                                // 'withdrawals'        => $card_member,

                            ], ['user_number' => $this->order['user_number']]);
                            if ($res->rowCount() == 0) {
                                dump_log('退款： ' . $this->order['order_number'] . ' 状态： 更新用户金额失败', 'cash_bonus_error.txt');
                                return false;
                            }
                            $res = $database->update('cecharge_order', [
                                'status'   => 'error',
                                'pay_list' => '订单超时',
                            ], [
                                'order_number' => $this->order['order_number'],
                            ]);
                            if ($res->rowCount() == 0) {
                                dump_log('退款： ' . $this->order['order_number'] . ' 状态： 更新用户金额失败', 'cash_bonus_error.txt');
                                return false;
                            }
                            var_dump('订单：' . $this->order['order_number'] . ' 成功为' . $this->order['user_number'] . '退款' . $this->order['balance'] . '元');

                            return true;

                        });

                    }
                    $res = $db->update('cecharge_order', [
                        'refund' => '已退款',
                    ], [
                        'order_number' => $this->order['order_number'],
                    ]);

                }

            }
        }

    }


    public function sendredpackAction()
    {
        $db = $this->mysql();

        $config    = $db->select('config', '*');
        $webConfig = [];
        foreach ($config as $key => $value) {
            $webConfig[$value['name']] = $value['value'];
        }
        file_put_contents('apiclient_key.pem', $webConfig['wechat_key']);
        file_put_contents('apiclient_cert.pem', $webConfig['wechat_cert']);

        $param = [
            'wxappid'      => $webConfig['appid'],
            'mch_id'       => $webConfig['mch_id'],
            'mch_billno'   => date('YmdHis') . rand(1000, 9999),
            'client_ip'    => ip(),
            're_openid'    => 'o5TKB4m00JorH8ubqNF7q86WU7GY',
            'total_amount' => 0.1 * 100,
            'total_num'    => 1,
            'send_name'    => '商家测试',
            'wishing'      => '恭喜发财',
            'act_name'     => '商家测试红包',
            'remark'       => '商家测试红包2',
            'nonce_str'    => $this->createNoncestr(),

        ];

        $param['sign'] = $this->getSign($param, $webConfig['pay_key']);

        $postXml     = $this->arrayToXml($param); //将参数转为xml格式
        $url         = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
        $responseXml = $this->postXmlSSLCurl($postXml, $url); //提交请求

        die(json_encode($this->xmlToArray($responseXml)));

        //$res = $this->pay($url, $obj2);
    }

    public function transfersAction()
    {
        $db         = $this->mysql();
        $this->data = $db->select('cash_draws', '*', [
            'status'     => ['已驳回', '打款中'],
            'refund'     => null,
            'deletetime' => null,
        ]);
        if (!empty($this->data)) {
            echo '<pre>';
            $config    = $db->select('config', '*');
            $webConfig = [];
            foreach ($config as $key => $value) {
                $webConfig[$value['name']] = $value['value'];
            }
            file_put_contents('apiclient_key.pem', $webConfig['wechat_key']);
            file_put_contents('apiclient_cert.pem', $webConfig['wechat_cert']);
            foreach ($this->data as $key => $value) {

                if ($value['status'] == '打款中') {
                    $wechatUserNumber = $db->get('user', 'wechat_user_number', [
                        'user_number' => $value['user_number'],
                    ]);
                    $openid = $db->get('wechat_user', 'openid', [
                        'wechat_user_number' => $wechatUserNumber,
                    ]);
                    $param = [
                        'mch_appid'        => $webConfig['appid'],
                        'mchid'            => $webConfig['mch_id'],
                        'partner_trade_no' => $value['cash_draws_number'],
                        'spbill_create_ip' => ip(),
                        'openid'           => $openid,
                        'check_name'       => 'NO_CHECK',
                        'amount'           => $value['amount'] * 100,
                        'desc'             => 'Kolay提现到账',
                        'nonce_str'        => $this->createNoncestr(),
                    ];
                    $param['sign'] = $this->getSign($param, $webConfig['pay_key']);
                    $postXml       = $this->arrayToXml($param); //将参数转为xml格式
                    $url           = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
                    $responseXml   = $this->postXmlSSLCurl($postXml, $url); //提交请求
                    $result        = $this->xmlToArray($responseXml);
                    if ($result['return_code'] == 'SUCCESS') {
                        $db->update('cash_draws', [
                            'status'     => '已完成',
                            'updatetime' => time(),
                        ], [
                            'cash_draws_number' => $value['cash_draws_number'],
                        ]);
                    }

                } else {

                    $withdrawals = $db->get('user', 'account_balance', [
                        'user_number'         => $value['user_number'],
                        'account_balance[>=]' => $value['amount'],
                    ]);

                    $db->insert('user_money_log', [
                        'order_number' => $value['cash_draws_number'],
                        'user_number'  => $value['user_number'],
                        'before'       => $withdrawals,
                        'money'        => $value['amount'],
                        'after'        => $value['amount'],
                        'state'        => '提现',
                        'type'         => '退款',
                        'createtime'   => time(),
                    ]);
                    $res = $db->update('user', [
                        'account_balance[+]' => $value['amount'],
                    ], [
                        'deletetime'  => null,
                        'state'       => 'normal',
                        'user_number' => $value['user_number'],
                    ]);
                    $db->update('cash_draws', [
                        'refund'     => '已退款',
                        'updatetime' => time(),
                    ], [
                        'cash_draws_number' => $value['cash_draws_number'],
                    ]);
                }
            }
        }
        die();

        //$res = $this->pay($url, $obj2);
    }
    //生成签名,参数：生成签名的参数和是否编码
    public function create_qianming($arr, $urlencode)
    {
        $buff = "";
        ksort($arr); 
        foreach ($arr as $k => $v) {
            if (null != $v && "null" != $v && "sign" != $k) {
                //签名不要转码
                if ($urlencode) {
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1); //去掉末尾符号“&”
        }
        return $reqPar;
    }
    public function xmlToArray($xml)
    {
        libxml_disable_entity_loader(true);
        return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    }
    //作用：产生随机字符串，不长于 32 位
    private function createNoncestr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str   = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     * 数组转xml
     * @param $arr
     * @return string
     */
    protected function arrayToXml($params)
    {

        if (!is_array($params) || count($params) <= 0) {
            return false;
        }
        $xml = "<xml>";
        foreach ($params as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }
    /**
     * 签名加密
     * @param $params
     * @param $key
     */
    protected function getSign($params, $key)
    {
        ksort($params, SORT_STRING);
        $unSignParaString = $this->formatQueryParaMap($params, false);
        return $signStr   = strtoupper(md5($unSignParaString . "&key=" . $key));
    }
    /**
     * 排序
     * @param $paraMap
     * @param bool $urlEncode
     * @return bool|string
     */
    protected function formatQueryParaMap($paraMap, $urlEncode = false)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if (null != $v && "null" != $v) {
                if ($urlEncode) {
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = '';
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }
    /**
     * 需要使用证书的请求
     * @param $xml
     * @param $url
     * @param int $second
     * @return bool|mixed
     */
    protected function postXmlSSLCurl($xml, $url, $second = 30)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLCERT, 'apiclient_cert.pem');
        curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLKEY, 'apiclient_key.pem');
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        $data = curl_exec($ch);
        if ($data) {
            curl_close($ch);
            // echo '<Pre>';
            // print_r($data);
            return $data;
        } else {
            $error = curl_errno($ch);
            echo "curl出错，错误码:$error" . "<br>";
            curl_close($ch);
            return false;
        }
    }
}
